package com.uama.image;

import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.widget.ImageView;

import com.facebook.binaryresource.BinaryResource;
import com.facebook.binaryresource.FileBinaryResource;
import com.facebook.cache.common.CacheKey;
import com.facebook.cache.disk.DiskCacheConfig;
import com.facebook.common.executors.CallerThreadExecutor;
import com.facebook.common.internal.Supplier;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.cache.DefaultCacheKeyFactory;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.core.ImagePipelineFactory;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.BasePostprocessor;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;

import java.io.File;

/**
 * @author wenhu Tong
 * @email wenhu.tong@uama.com.cn
 * @date 2017/11/8 16:57
 * @desc
 */
public class ImageLoader {
    private static final String PHOTO_FRESCO = "frescoCache";
    private static final int DEFAULT_DISK_CACHE = 50 * 1024 * 1024;

    private volatile static ImageLoader mInstance;
    private int diskCacheSize = DEFAULT_DISK_CACHE;
    private Context mContext;

    private ImageLoader() {
    }

    public interface LoaderListener {
        void onSuccess(Bitmap bitmap);

        void onFailed(String err);
    }

    public static ImageLoader getInstance() {
        if (mInstance == null) {
            synchronized (ImageLoader.class) {
                if (mInstance == null) {
                    mInstance = new ImageLoader();
                }
            }
        }
        return mInstance;
    }

    public void init(Context context) {
        mContext = context;
        initImageLoader(context);
    }



    public void load(@NonNull ImageView imageView, String url) {
        loadAnimation(imageView, getUri(url));
    }

    public void load(@NonNull ImageView imageView, @DrawableRes int resID) {
        loadAnimation( imageView, getUri(resID));
    }

    public void load(@NonNull ImageView imageView, Uri uri) {
        if (imageView instanceof SimpleDraweeView) {
            ((SimpleDraweeView) imageView).setImageURI(uri);
        }
    }

    public void load(@NonNull String url, @NonNull LoaderListener listener) {
        getFrescoImgProcessor(mContext, getUri(url), 0, 0, null, listener);
    }

    public void load(@NonNull @DrawableRes int resID, @NonNull LoaderListener listener) {
        getFrescoImgProcessor(mContext, getUri(resID), 0, 0, null, listener);
    }

    public void pause() {
        Fresco.getImagePipeline().pause();
    }

    public boolean isCached(Uri uri) {
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource<Boolean> dataSource = imagePipeline.isInDiskCache(uri);
        if (dataSource == null) {
            return false;
        }
        ImageRequest imageRequest = ImageRequest.fromUri(uri);
        CacheKey cacheKey = DefaultCacheKeyFactory.getInstance()
                .getEncodedCacheKey(imageRequest, mContext);
        BinaryResource resource = ImagePipelineFactory.getInstance()
                .getMainFileCache().getResource(cacheKey);
        return resource != null && dataSource.getResult() != null && dataSource.getResult();
    }

    public File getCache(Uri uri) {
        if (!isCached(uri))
            return null;
        ImageRequest imageRequest = ImageRequest.fromUri(uri);
        CacheKey cacheKey = DefaultCacheKeyFactory.getInstance()
                .getEncodedCacheKey(imageRequest, mContext);
        BinaryResource resource = ImagePipelineFactory.getInstance()
                .getMainFileCache().getResource(cacheKey);
        File file = ((FileBinaryResource) resource).getFile();
        return file;
    }

    public void clearDiskCache() {
        Fresco.getImagePipeline().clearDiskCaches();
    }


    public void resume() {
        Fresco.getImagePipeline().resume();
    }

    public Uri getUri(@NonNull String url) {

        if (url.startsWith("http")) {
            return Uri.parse(url);
        } else {
            return Uri.fromFile(new File(url));
        }
    }

    public Uri getUri(@DrawableRes int resId) {
        return Uri.parse("res://uama/" + resId);
    }

    private void loadAnimation(@NonNull ImageView imageView, @NonNull Uri uri) {
        if (imageView instanceof SimpleDraweeView) {
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setUri(uri)
                    .setAutoPlayAnimations(true)
                    .build();
            ((SimpleDraweeView)imageView).setController(controller);
        }
    }

    private void initImageLoader(final Context context) {
        DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context)
                .setMaxCacheSize(diskCacheSize)
                .setBaseDirectoryName(PHOTO_FRESCO)
                .setBaseDirectoryPathSupplier(new Supplier<File>() {
                    @Override
                    public File get() {
                        return context.getCacheDir();
                    }
                })
                .build();

        ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
                .setMainDiskCacheConfig(diskCacheConfig)
                .setDownsampleEnabled(true)
                .setBitmapsConfig(Bitmap.Config.RGB_565)
                .build();
        Fresco.initialize(context, config);
    }

    private void getFrescoImgProcessor(Context context, final Uri uri, final int width, final int height,
                                       BasePostprocessor processor, final LoaderListener listener) {

        ResizeOptions resizeOptions = null;
        if (width != 0 && height != 0) {
            resizeOptions = new ResizeOptions(width, height);
        }
        ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(false)
                .setPostprocessor(processor)
                .setResizeOptions(resizeOptions)
                .build();
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
        dataSource.subscribe(new BaseBitmapDataSubscriber() {
            @Override
            protected void onNewResultImpl(Bitmap bitmap) {
                //图片不能是GIF
                listener.onSuccess(bitmap);
            }

            @Override
            protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                listener.onFailed(dataSource.getFailureCause().getMessage());
            }
        }, CallerThreadExecutor.getInstance());
    }

}
